package com.binance.binancedemo.recycler;

import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.binance.binancedemo.utils.L;


/**
 */
public abstract class BaseRecyclerCell<T, VH extends BaseRecyclerViewHolder> implements BaseRecyclerViewHolder.OnViewRecycledListener {

    private boolean mIsShown;

    protected T mData;
    public VH mViewHolder;
    public BaseRecyclerAdapter mAdapter;
    protected RecyclerView mRecyclerView;
    protected boolean mDestroyed;
    private Rect mDecorationRect;

    public BaseRecyclerCell(T t) {
        mData = t;
    }

    public abstract void reloadResource();

    public abstract void releaseResource();

    public abstract VH createViewHolder(ViewGroup parent);

    protected abstract void onBindViewHolder(VH viewHolder);

    public abstract int getType();

    public void onViewRecycled() {
        mViewHolder = null;
    }

    public final void bindViewHolder(VH viewHolder) {
        mViewHolder = viewHolder;
        if (mViewHolder != null) {
            mViewHolder.setOnViewRecycledListener(this);
        }
        setShown(true);
        onBindViewHolder(viewHolder);
    }

    public void updateData(T mData) {
        this.mData = mData;
        if (mViewHolder != null) {
            onBindViewHolder(mViewHolder);
        }
    }

    public T getData() {
        return mData;
    }

    public <C extends BaseRecyclerCell, VH extends BaseRecyclerViewHolder> void setAdapter(BaseRecyclerAdapter<C, VH> adapter) {
        this.mAdapter = adapter;
    }

    protected BaseRecyclerViewHolder createHolderByLayout(int layoutId, ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
        return new BaseRecyclerViewHolder(view);
    }

    protected void onDestroyView() {
        mDestroyed = true;
        mViewHolder = null;
        mAdapter = null;
        mRecyclerView = null;
    }

    @Override
    public int hashCode() {
        if (mData != null) {
            return mData.hashCode();
        }
        return super.hashCode();
    }


    public boolean isShown() {
        return mIsShown;
    }

    public void setShown(boolean shown) {
        //之前不可见，现在可见
        if (!mIsShown && shown) {
            if (checkShowVisible()) {
                onShow();
            } else {
                return;
            }
        }

        if (mIsShown && !shown) {
            onHide();
        }

        mIsShown = shown;
    }

    protected void onHide() {
    }

    protected void onShow() {
    }

    /**
     * @return [0~1]在屏幕上展示面积超过此区域才会下发{@link #onShow()}事件
     */
    public float getVisibleAreaForShowEvent() {
        return 0;
    }

    public boolean checkShowVisible() {
        if (mViewHolder == null || mViewHolder.itemView == null || mViewHolder.itemView.getParent() == null) {
            return false;
        }
        float rate = getVisibleAreaForShowEvent();
        if (rate <= 0 || rate >= 1) {
            return true;
        }
        View recyclerView = (View) mViewHolder.itemView.getParent();
        int top = mViewHolder.itemView.getTop();
        int bottom = mViewHolder.itemView.getBottom();
        int parentHeight = recyclerView.getHeight();
        if (bottom < 0 || top > parentHeight) {
            //完全在屏幕外
            L.i(getClass().getSimpleName() + "完全在屏幕外:" + false);
            return false;
        }
        if ((top <= 0 && bottom >= parentHeight) || (top > 0 && bottom < parentHeight)) {
            //整个屏幕都没显示完或完全在屏幕内
            L.i(getClass().getSimpleName() + "完全展示:" + true);
            return true;
        }
        int itemHeight = mViewHolder.itemView.getHeight();
        float showRate;
        if (top < 0) {
            //在顶上尾巴露出来了
            showRate = bottom / (float) itemHeight;
        } else {
            //在底下头漏出来了
            showRate = (parentHeight - top) / (float) itemHeight;
        }
        L.i(getClass().getSimpleName() + "展示面积:" + showRate + " 要求展示面积:" + rate + " " + (showRate > rate));
        return showRate > rate;
    }

    public Rect getDecorationRect() {
        return mDecorationRect;
    }

    public void setDecorationRect(Rect decorationRect) {
        mDecorationRect = decorationRect;
    }

    public void setRecyclerView(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
    }

    protected boolean areItemsTheSame(BaseRecyclerCell cell) {
        if (cell == null) {
            return false;
        }
        return getClass().isInstance(cell);
    }

    protected boolean areContentsTheSame(BaseRecyclerCell cell) {
        if (cell == null) {
            return false;
        }
        DiffMode diffMode = getDiffMode();
        if (diffMode != null && diffMode == DiffMode.UNIQUE) {
            return getClass().isInstance(cell);
        }
        /** 默认是{@link DiffMode#DATA}模式*/
        return isDataEquals(cell.getData());
    }

    protected boolean isDataEquals(Object b) {
        return (mData == b) || (mData != null && mData.equals(b));
    }

    protected DiffMode getDiffMode() {
        return DiffMode.DATA;
    }

    @Nullable
    protected Object getChangePayload(BaseRecyclerCell cell) {
        return null;
    }
}
